# Author: Cascade
# Date: 2024/06/22
# Description: Fish Speech TTS Service Implementation

import os
import logging
import requests
import numpy as np
import soundfile as sf
from typing import Optional
from pathlib import Path
from pptflow.tts.tts_service import TtsService
from pptflow.config.setting import Setting
from pptflow.utils import mylogger

logger = mylogger.get_logger(__name__)

class FishSpeechTtsService(TtsService):
    """
    Fish Speech TTS Service Implementation
    Fish Speech is a powerful TTS engine with good Chinese support
    """
    
    def __init__(self):
        self.base_url = os.getenv("FISH_SPEECH_API", "http://localhost:8330")
        self.model_name = os.getenv("FISH_SPEECH_MODEL", "fish-speech-1.1")
        self.speaker = os.getenv("FISH_SPEECH_SPEAKER", "default")
        logger.info(f"Initialized FishSpeechTtsService with {self.base_url}")

    async def tts(self, text: str, output_audio_filename: str, setting: Setting):
        """
        Convert text to speech using Fish Speech
        
        Args:
            text: The text to convert to speech
            output_audio_filename: Path to save the generated audio
            setting: Application settings
        """
        try:
            if not text.strip():
                logger.warning("Empty text provided for TTS")
                return
                
            # Prepare the request payload
            payload = {
                "text": text,
                "model": self.model_name,
                "speaker": self.speaker,
                "language": "zh" if any('\u4e00' <= char <= '\u9fff' for char in text) else "en",
                "speed": 1.0,
                "format": "wav"
            }
            
            # Make the API request
            response = requests.post(
                f"{self.base_url}/tts",
                json=payload,
                headers={"Content-Type": "application/json"},
                timeout=30
            )
            
            # Check for errors
            response.raise_for_status()
            
            # Save the audio
            with open(output_audio_filename, 'wb') as f:
                f.write(response.content)
                
            logger.info(f"Successfully generated speech: {output_audio_filename}")
            
        except Exception as e:
            logger.error(f"Error in Fish Speech TTS: {str(e)}")
            raise
    
    def get_voice_list(self, setting: Setting = None) -> list:
        """
        Get available voices from Fish Speech
        """
        try:
            response = requests.get(f"{self.base_url}/voices", timeout=10)
            response.raise_for_status()
            return response.json().get('voices', ['default'])
        except Exception as e:
            logger.warning(f"Could not fetch voices from Fish Speech: {e}")
            return ['default']


# For testing
if __name__ == "__main__":
    import asyncio
    
    # Test the TTS service
    async def test():
        tts = FishSpeechTtsService()
        await tts.tts(
            "这是一个测试，测试Fish Speech中文合成效果。",
            "test_fish_speech.wav",
            Setting()
        )
        print("Test completed. Check test_fish_speech.wav")
    
    asyncio.run(test())
